Modelos#

# Librerias

import warnings
warnings.filterwarnings('ignore')
import pandas as pd
import numpy as np
import plotly.graph_objects as go
import plotly.figure_factory as ff
import plotly.express as px

# Librerias para modelos

from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import mean_absolute_percentage_error, mean_squared_error, r2_score, make_scorer
from sklearn.linear_model import Ridge
from sklearn.linear_model import Lasso
from xgboost import XGBRegressor
from sklearn.neural_network import MLPRegressor
import joblib

from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder
# Definir la paleta de colores personalizada
custom_colors = ['#1F3040', '#B9CDCA', '#F2C6AC', '#D99982', '#735749']
# Cargar datos
ventas = pd.read_csv('C:/UNINORTE/VC/Proyecto2/Archivos_Finales/datosventas.csv')
ventas.describe().T
count mean std min 25% 50% 75% max
lat 155105.0 5.652091e+00 2.204566e+00 3.254000e+00 4.648077e+00 4.721532e+00 6.210060e+00 1.104366e+01
long 155105.0 -7.487562e+01 8.883420e-01 -7.657500e+01 -7.557198e+01 -7.420027e+01 -7.406731e+01 -7.396190e+01
price 155105.0 4.984872e+08 4.051956e+08 2.000000e+06 2.400000e+08 3.750000e+08 6.000000e+08 4.900000e+09
rooms 155105.0 3.003527e+00 1.033709e+00 1.000000e+00 2.000000e+00 3.000000e+00 3.000000e+00 7.000000e+00
baths 155105.0 2.559737e+00 1.121071e+00 0.000000e+00 2.000000e+00 2.000000e+00 3.000000e+00 7.000000e+00
park 155105.0 1.182457e+00 9.385399e-01 0.000000e+00 1.000000e+00 1.000000e+00 2.000000e+00 5.000000e+00
area_privada 155105.0 1.114881e+02 6.199171e+01 1.000000e+00 6.500000e+01 9.400000e+01 1.390000e+02 3.250000e+02
area_const 155105.0 1.139092e+02 6.337710e+01 1.000000e+00 6.600000e+01 9.600000e+01 1.440000e+02 3.319651e+02
admon 155105.0 3.498544e+05 2.571560e+05 0.000000e+00 1.600000e+05 2.840000e+05 4.790000e+05 2.118338e+06
Estrato 155105.0 4.101970e+00 9.879393e-01 1.000000e+00 3.000000e+00 4.000000e+00 5.000000e+00 6.000000e+00
Piso No 112509.0 3.753531e+00 3.098129e+00 1.000000e+00 1.000000e+00 3.000000e+00 5.000000e+00 1.600000e+01
ventas.head()
lat long category price rooms baths park ciudad barrio area_privada area_const admon Estrato Estado Antiguedad Piso No Tipo de Apartamento Sector
0 3.377575 -76.523969 Apartamento 197000000.0 2 2 1 Cali Ciudad Bochalema 64.0 64.0 178000.000000 4 No Especificado 1 a 8 años NaN No Especificado Ciudad Bochalema
1 4.563951 -74.107534 Apartaestudio 70000000.0 1 1 0 Bogotá Las Lomas 30.0 30.0 45000.000000 2 No Especificado 16 a 30 años NaN No Especificado Las Lomas
2 6.264103 -75.603076 Apartamento 235000000.0 3 2 1 Medellín Calasanz Occidente 56.0 56.0 192139.000000 3 No Especificado No Especificado 13.0 No Especificado No Especificado
3 10.993099 -74.817276 Apartaestudio 139000000.0 1 1 1 Barranquilla Ciudad Jardín 43.0 43.0 145000.000000 4 No Especificado No Especificado 4.0 No Especificado No Especificado
4 6.248413 -75.563910 Apartamento 260000000.0 4 2 0 Medellín Centro 115.0 115.0 177878.235981 4 4.0 9 a 15 años 3.0 No Especificado Centro
# Seleccionar columnas numericas
columnas_numericas = ventas.select_dtypes(include=['int', 'float']).columns

# Guardar los nombres de las columnas numericas en una lista
nombre_columna_numericas = list(columnas_numericas )

# Calcular la matriz de correlación
corr_matrix = ventas[nombre_columna_numericas].corr()

# Crear el gráfico de la matriz de correlación
fig = ff.create_annotated_heatmap(
    z=corr_matrix.to_numpy(),
    x=list(corr_matrix.columns),
    y=list(corr_matrix.index),
    annotation_text=corr_matrix.round(2).to_numpy(),
    showscale=True,
    colorscale=custom_colors
)
fig.update_layout(title='Matriz de Correlación', xaxis_title='Variables', yaxis_title='Variables')
fig.show()

Preprocesamiento#

Dado que las variables ‘lat’ y ‘long’ explican lo mismo que las variables ‘ciudad’, ‘barrio’ y ‘sector’, lo cual es más que evidente en la gráfica de associations de vista en el EDA; para nuestras predicciones utilizaremos solo ‘lat’ y ‘long’.

La variable ‘Piso No’ también será excluida de nuestro análisis al tener demasiados valores nulos, que no pudieron ser imputados con ninguna técnica de imputación, adicionalmente solo tiene una explicación para una de las categorías de inmuebles.

Por otro lado, las variables ‘area_privada’ y ‘area_const’ tienen una correlación de 0.98, por ende, solo utilizaremos una de ellas, en este caso ‘area_const’.

ventas = ventas.drop(['ciudad','barrio', 'Piso No', 'Sector','area_privada'],axis=1)
# Seleccionar columnas categóricas
columnas_categoricas = ventas.select_dtypes(include=['object', 'category']).columns

# Guardar los nombres de las columnas categóricas en una lista
nombre_columna_categorica = list(columnas_categoricas)

# Seleccionar columnas numericas
columnas_numericas = ventas.select_dtypes(include=['int', 'float']).columns

# Guardar los nombres de las columnas numericas en una lista
nombre_columna_numericas = list(columnas_numericas )

# Mostrar la lista de nombres de columnas
print(nombre_columna_categorica)
print(nombre_columna_numericas)
['category', 'Estado', 'Antiguedad', 'Tipo de Apartamento']
['lat', 'long', 'price', 'rooms', 'baths', 'park', 'area_const', 'admon', 'Estrato']
# Separar datos en variables predictoras y variable de interes
X = ventas.drop(['price'],axis=1)
y = ventas['price']

# Dividir los datos en conjuntos de entrenamiento y prueba
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=68)
def calcular_metricas(X_trainval, y_trainval, X_test, y_test, best_model):

    # Realizar predicciones en el conjunto de entrenamiento (X_trainval)
    y_pred_train = best_model.predict(X_trainval)

    # Realizar predicciones en el conjunto de prueba (X_test)
    y_pred_test = best_model.predict(X_test)

    # Calcular las métricas utilizando los datos de entrenamiento y validación
    mape_tra = mean_absolute_percentage_error(y_trainval, y_pred_train)
    rmse_tra = np.sqrt(mean_squared_error(y_trainval, y_pred_train))
    r2_tra = r2_score(y_trainval, y_pred_train)

    # Calcular las métricas utilizando los datos de prueba (X_test, y_test)
    mape_test = mean_absolute_percentage_error(y_test, y_pred_test)
    rmse_test = np.sqrt(mean_squared_error(y_test, y_pred_test))
    r2_test = r2_score(y_test, y_pred_test)

    return mape_tra, rmse_tra, r2_tra, mape_test, rmse_test, r2_test
def plot_residuals(y_true, y_pred):
    # Calcula los residuos
    residuos = y_true - y_pred
    
    # Gráfico de dispersión de residuos
    fig = go.Figure()
    fig.add_trace(go.Scatter(x=y_pred, y=residuos, mode='markers', name='Residuos',
                             marker=dict(color=custom_colors[3])))
    fig.add_hline(y=0, line_dash="dash", line_color=custom_colors[0])
    fig.update_layout(
        title='Diagrama de Residuos',
        xaxis_title='Valores Predichos',
        yaxis_title='Residuos',
        showlegend=False
    )
    fig.show()

    # Histograma de los residuos
    fig = go.Figure()
    fig.add_trace(go.Histogram(x=residuos, marker_color=custom_colors[2]))
    fig.update_layout(
        title='Histograma de Residuos',
        xaxis_title='Residuos',
        yaxis_title='Frecuencia',
        bargap=0.05
    )
    fig.show()
def plot_real_vs_predicted(y_real, y_pred, filename):
    # Crear DataFrame con los valores reales y predichos
    df = pd.DataFrame({
        'Y Real': y_real,
        'Y Predicho': y_pred
    })
    
    # Guardar los datos en un archivo CSV
    #df.to_csv(filename, index=False)
    
    # Crear el gráfico de dispersión para comparar los valores reales y predichos
    fig = go.Figure()
    fig.add_trace(go.Scatter(x=y_real, y=y_pred, mode='markers', name='Real vs Predicho',
                             marker=dict(color=custom_colors[3])))
    fig.add_trace(go.Scatter(x=y_real, y=y_real, mode='lines', name='Comportamiento Ideal',
                             line=dict(color=custom_colors[0], dash='dash')))
    
    fig.update_layout(title='Comparación de Y Real vs Y Predicho',
                      xaxis_title='Y Real',
                      yaxis_title='Y Predicho',
                      legend_title='Leyenda')
    fig.show()

Modelo Ridge#

# Identificar las columnas categóricas
#categorical_features = nombre_columna_categorica  

#column_transformer = ColumnTransformer(
#    transformers=[
#        ('cat', OneHotEncoder(handle_unknown='ignore'), categorical_features)
#   ],
#    remainder='passthrough'  # esto pasa las otras columnas numéricas sin cambios
#)

## Crear un pipeline que primero transforme los datos y luego aplique el modelo Ridge
#pipeline = Pipeline(steps=[
#    ('preprocessor', column_transformer),
#    ('regressor', Ridge())
#])

## Definir los parámetros para buscar utilizando GridSearchCV
#param_grid = {
#    'regressor__alpha': [0.1, 1, 10, 50, 100, 200, 1000],  # Diferentes valores de regularización
#    'regressor__solver': ['auto', 'svd', 'cholesky', 'lsqr', 'sparse_cg']
#}

## Definir el scorer para el GridSearchCV
#mse_scorer = make_scorer(mean_squared_error, greater_is_better=False)

## Realizar una búsqueda de cuadrícula para encontrar los mejores parámetros
#grid_search = GridSearchCV(pipeline, param_grid, cv=5, scoring=mse_scorer, verbose=2, n_jobs=-1)
#grid_search.fit(X_train, y_train)

## El mejor modelo resultante del GridSearchCV
#best_model = grid_search.best_estimator_

best_model = joblib.load("mejor_modelo_ridge.joblib")

# Calcular las métricas para el mejor modelo
mape_ridget, rmse_ridget, r2_ridget, mape_ridge, rmse_ridge, r2_ridge = calcular_metricas(X_train, y_train, X_test, y_test, best_model)

# Imprimir las métricas
print(f'MAPE en el conjunto de entrenamiento: {mape_ridget}')
print(f'RMSE en el conjunto de entrenamiento: {rmse_ridget}')
print(f'R^2 en el conjunto de entrenamiento: {r2_ridget}')
#print("Mejores parámetros encontrados: ", grid_search.best_params_)

# Imprimir las métricas
print(f'MAPE en el conjunto de prueba: {mape_ridge}')
print(f'RMSE en el conjunto de prueba: {rmse_ridge}')
print(f'R^2 en el conjunto de prueba: {r2_ridge}')

# Guardar el modelo en un archivo
#joblib.dump(best_model, 'mejor_modelo_ridge.joblib')
MAPE en el conjunto de entrenamiento: 0.3270766638873291
RMSE en el conjunto de entrenamiento: 196719169.17808387
R^2 en el conjunto de entrenamiento: 0.765151663063854
MAPE en el conjunto de prueba: 0.3328104239732556
RMSE en el conjunto de prueba: 196370084.51321307
R^2 en el conjunto de prueba: 0.7616582800487592
y_pred = best_model.predict(X_test)

plot_residuals(y_test, y_pred)
feature_names = X_test.columns.tolist()
plot_real_vs_predicted(y_test, y_pred, filename='real_vs_predicted_ridge.csv')
# Acceder al modelo Ridge y a los coeficientes dentro del pipeline
ridge_model = best_model.named_steps['regressor']
ridge_coefs = ridge_model.coef_

# Acceder a los nombres de las características transformadas
feature_names_transformed = best_model.named_steps['preprocessor'].get_feature_names_out()

# Crear DataFrame para los coeficientes y características
if len(feature_names_transformed) != len(ridge_coefs):
    print("La longitud de los nombres de las características transformadas no coincide con los coeficientes.")
else:
    coefs = pd.DataFrame({
        'feature': feature_names_transformed,
        'coefficient': ridge_coefs
    })
    coefs['abs_coefficient'] = coefs['coefficient'].abs()

    # Ordenar las características por la importancia absoluta de sus coeficientes de mayor a menor
    coefs = coefs.sort_values(by='abs_coefficient')
    
    # Guardar en un archivo CSV
    #coefs.to_csv('FeatureImportances_ridge.csv', index=False)

    # Creando el gráfico con Plotly
    fig = px.bar(coefs, y='feature', x='abs_coefficient', orientation='h',
                 title='Importancia de las Características - Ridge Regression', color_discrete_sequence=custom_colors)
    fig.show()

Modelo Lasso#

## Identificar las columnas categóricas
#categorical_features = nombre_columna_categorica  

#column_transformer = ColumnTransformer(
#    transformers=[
#        ('cat', OneHotEncoder(handle_unknown='ignore'), categorical_features)
#    ],
#    remainder='passthrough'  # esto pasa las otras columnas numéricas sin cambios
#)

## Crear un pipeline que primero transforme los datos y luego aplique el modelo Lasso
#pipeline = Pipeline(steps=[
#    ('preprocessor', column_transformer),
#    ('regressor', Lasso(random_state=0))
#])

## Definir los parámetros para buscar utilizando GridSearchCV
#param_grid = {
#    'regressor__alpha': [0.001, 0.01, 0.1, 1.0, 10, 100],  # Diferentes valores de regularización
#    'regressor__max_iter': [1000, 5000, 10000],  # Ajustar si es necesario para asegurar la convergencia
#    'regressor__fit_intercept': [True, False],
#}

## Definir el scorer para el GridSearchCV
#mse_scorer = make_scorer(mean_squared_error, greater_is_better=False)

## Realizar una búsqueda de cuadrícula para encontrar los mejores parámetros
#grid_search = GridSearchCV(pipeline, param_grid, cv=5, scoring=mse_scorer, verbose=2, n_jobs=-1)
#grid_search.fit(X_train, y_train)

# El mejor modelo resultante del GridSearchCV
best_model = joblib.load("mejor_modelo_lasso.joblib")

# Calcular las métricas para el mejor modelo
mape_lassot, rmse_lassot, r2_lassot, mape_lasso, rmse_lasso, r2_lasso = calcular_metricas(X_train, y_train, X_test, y_test, best_model)

# Imprimir las métricas
print(f'MAPE en el conjunto de entrenamiento: {mape_lassot}')
print(f'RMSE en el conjunto de entrenamiento: {rmse_lassot}')
print(f'R^2 en el conjunto de entrenamiento: {r2_lassot}')
#print("Mejores parámetros encontrados: ", grid_search.best_params_)

# Imprimir las métricas
print(f'MAPE en el conjunto de prueba: {mape_lasso}')
print(f'RMSE en el conjunto de prueba: {rmse_lasso}')
print(f'R^2 en el conjunto de prueba: {r2_lasso}')

## Guardar el modelo en un archivo
#joblib.dump(best_model, 'mejor_modelo_lasso.joblib')
MAPE en el conjunto de entrenamiento: 0.32706308906856385
RMSE en el conjunto de entrenamiento: 196718801.4310985
R^2 en el conjunto de entrenamiento: 0.7651525411144026
MAPE en el conjunto de prueba: 0.3328245848799931
RMSE en el conjunto de prueba: 196372547.9475254
R^2 en el conjunto de prueba: 0.7616523000864321
y_pred = best_model.predict(X_test)

plot_residuals(y_test, y_pred)
feature_names = X_test.columns.tolist()
plot_real_vs_predicted(y_test, y_pred, filename='real_vs_predicted_lasso.csv')
# Acceder al modelo Lasso y a los coeficientes dentro del pipeline
lasso_model = best_model.named_steps['regressor']
lasso_coefs = lasso_model.coef_

# Acceder a los nombres de las características transformadas
feature_names_transformed = best_model.named_steps['preprocessor'].get_feature_names_out()

# Crear DataFrame para los coeficientes y características
if len(feature_names_transformed) != len(lasso_coefs):
    print("La longitud de los nombres de las características transformadas no coincide con los coeficientes.")
else:
    coefs = pd.DataFrame({
        'feature': feature_names_transformed,
        'coefficient': lasso_coefs
    })
    coefs['abs_coefficient'] = coefs['coefficient'].abs()

    # Ordenar las características por la importancia absoluta de sus coeficientes de mayor a menor
    coefs = coefs.sort_values(by='abs_coefficient')
    
    # Guardar en un archivo CSV
    #coefs.to_csv('FeatureImportances_lasso.csv', index=False)

    # Creando el gráfico con Plotly
    fig = px.bar(coefs, y='feature', x='abs_coefficient', orientation='h',
                 title='Importancia de las Características - Lasso Regression', color_discrete_sequence=custom_colors)
    fig.show()

Modelo XGBoots#

## Identificar las columnas categóricas
#categorical_features = nombre_columna_categorica  

#column_transformer = ColumnTransformer(
#    transformers=[
#        ('cat', OneHotEncoder(handle_unknown='ignore'), categorical_features)
#    ],
#    remainder='passthrough'  # esto pasa las otras columnas numéricas sin cambios
#)

## Crear un pipeline que primero transforme los datos y luego aplique el modelo XGBoost
#pipeline = Pipeline(steps=[
#    ('preprocessor', column_transformer),
#    ('regressor', XGBRegressor(objective='reg:squarederror', random_state=0))
#])

## Definir los parámetros para buscar utilizando GridSearchCV
#param_grid = {
#    'regressor__n_estimators': [50, 100, 200],
#    'regressor__learning_rate': [0.01, 0.1, 0.3],
#    'regressor__max_depth': [3, 5, 7]
#}

## Definir el scorer para el GridSearchCV
#mse_scorer = make_scorer(mean_squared_error, greater_is_better=False)

## Realizar una búsqueda de cuadrícula para encontrar los mejores parámetros
#grid_search = GridSearchCV(pipeline, param_grid, cv=5, scoring=mse_scorer, verbose=2, n_jobs=-1)
#grid_search.fit(X_train, y_train)

# El mejor modelo resultante del GridSearchCV
best_model = joblib.load("mejor_modelo_xgboots.joblib")

# Calcular las métricas para el mejor modelo
mape_xgboostt, rmse_xgboostt, r2_xgboostt, mape_xgboost, rmse_xgboost, r2_xgboost = calcular_metricas(X_train, y_train, X_test, y_test, best_model)

# Imprimir las métricas
print(f'MAPE en el conjunto de entrenamiento: {mape_xgboostt}')
print(f'RMSE en el conjunto de entrenamiento: {rmse_xgboostt}')
print(f'R^2 en el conjunto de entrenamiento: {r2_xgboostt}')
#print("Mejores parámetros encontrados: ", grid_search.best_params_)

# Imprimir las métricas
print(f'MAPE en el conjunto de prueba: {mape_xgboost}')
print(f'RMSE en el conjunto de prueba: {rmse_xgboost}')
print(f'R^2 en el conjunto de prueba: {r2_xgboost}')

## Guardar el modelo en un archivo
#joblib.dump(best_model, 'mejor_modelo_xgboots.joblib')
MAPE en el conjunto de entrenamiento: 0.1335809267109008
RMSE en el conjunto de entrenamiento: 72816745.63153034
R^2 en el conjunto de entrenamiento: 0.9678221771360337
MAPE en el conjunto de prueba: 0.1924401789399948
RMSE en el conjunto de prueba: 107622322.47698922
R^2 en el conjunto de prueba: 0.9284097078636615
y_pred = best_model.predict(X_test)

plot_residuals(y_test, y_pred)
feature_names = X_test.columns.tolist()
plot_real_vs_predicted(y_test, y_pred, filename='real_vs_predicted_XGBoots.csv')
##'best_model' es tu modelo XGBoost ya entrenado dentro de un pipeline
#xgb_model = best_model.named_steps['regressor']

## Obtener las importancias de las características. Asumiendo que el modelo está entrenado.
#feature_importances = xgb_model.feature_importances_

## Acceder a los nombres de las características transformadas
#feature_names_transformed = best_model.named_steps['preprocessor'].get_feature_names_out()

## Crear DataFrame para las importancias de características
#importances = pd.DataFrame({
#    'feature': feature_names_transformed,
#    'importance': feature_importances
#})

# Ordenar las características por la importancia de mayor a menor
#importances_sorted = importances.sort_values(by='importance')
importances_sorted = pd.read_csv('C:/UNINORTE/VC/Proyecto2/Archivos_Finales/FeatureImportances_xgboost.csv')

# Guardar en un archivo CSV
#importances_sorted.to_csv('FeatureImportances_xgboost.csv', index=False)

# Crear el gráfico con Plotly
fig = px.bar(importances_sorted, x='importance', y='feature', title='Importancia de las Características - XGBoost',
             labels={'feature': 'Características', 'importance': 'Importancia'},
             orientation='h', color_discrete_sequence=custom_colors)
fig.show()

Modelo MLP#

## Identificar las columnas categóricas
#categorical_features = nombre_columna_categorica

#column_transformer = ColumnTransformer(
#    transformers=[
#        ('cat', OneHotEncoder(handle_unknown='ignore'), categorical_features)
#    ],
#    remainder='passthrough'  # Esto pasa las otras columnas numéricas sin cambios
#)

## Crear un pipeline que primero transforme los datos y luego aplique el modelo MLP
#pipeline = Pipeline(steps=[
#    ('preprocessor', column_transformer),
#    ('regressor', MLPRegressor(random_state=1))
#])

## Definir los parámetros para buscar utilizando GridSearchCV
#param_grid = {
#    'regressor__hidden_layer_sizes': [(50,), (100,)],  # Varias configuraciones de capas ocultas
#    'regressor__alpha': [0.001, 0.01, 0.1],  # Rango extendido de parámetro de regularización L2
#    'regressor__learning_rate_init': [0.005, 0.01],  # Tasa de aprendizaje inicial con más opciones
#    'regressor__max_iter': [200, 300],  # Rango extendido de número máximo de iteraciones
#}

## Definir el scorer para el GridSearchCV
#mse_scorer = make_scorer(mean_squared_error, greater_is_better=False)

## Realizar una búsqueda de cuadrícula para encontrar los mejores parámetros
#grid_search = GridSearchCV(pipeline, param_grid, cv=5, scoring=mse_scorer, verbose=2, n_jobs=-1)
#grid_search.fit(X_train, y_train)

# El mejor modelo resultante del GridSearchCV
best_model = joblib.load("mejor_modelo_mpl.joblib")

## Imprimir las métricas
#print("Mejores parámetros encontrados: ", grid_search.best_params_)

# Calcular las métricas para el mejor modelo
mape_mlpt, rmse_mlpt, r2_mlpt, mape_mlp, rmse_mlp, r2_mlp = calcular_metricas(X_train, y_train, X_test, y_test, best_model)

# Imprimir las métricas
print(f'MAPE en el conjunto de entrenamiento: {mape_mlpt}')
print(f'RMSE en el conjunto de entrenamiento: {rmse_mlpt}')
print(f'R^2 en el conjunto de entrenamiento: {r2_mlpt}')
#print("Mejores parámetros encontrados: ", grid_search.best_params_)

# Imprimir las métricas
print(f'MAPE en el conjunto de prueba: {mape_mlp}')
print(f'RMSE en el conjunto de prueba: {rmse_mlp}')
print(f'R^2 en el conjunto de prueba: {r2_mlp}')

## Guardar el modelo en un archivo
#joblib.dump(best_model, 'mejor_modelo_mpl.joblib')
MAPE en el conjunto de entrenamiento: 0.29659783428441644
RMSE en el conjunto de entrenamiento: 192515342.27320886
R^2 en el conjunto de entrenamiento: 0.775081686909593
MAPE en el conjunto de prueba: 0.30390329713346426
RMSE en el conjunto de prueba: 194189460.07168415
R^2 en el conjunto de prueba: 0.7669223002370361
y_pred = best_model.predict(X_test)

plot_residuals(y_test, y_pred)
feature_names = X_test.columns.tolist()
plot_real_vs_predicted(y_test, y_pred, filename='real_vs_predicted_MLP.csv')
# 'best_model' es el modelo MLP ya entrenado dentro de un pipeline
mlp_model = best_model.named_steps['regressor']

# Acceder a los pesos de la primera capa oculta
weights_first_layer = mlp_model.coefs_[0]  # Coefs_ es una lista de matrices de coeficientes

# Calcular la importancia aproximada de las características como la suma de los valores absolutos de los pesos
feature_importances = np.sum(np.abs(weights_first_layer), axis=1)

# Acceder a los nombres de las características transformadas
feature_names_transformed = best_model.named_steps['preprocessor'].get_feature_names_out()

# Crear DataFrame para las importancias aproximadas
coefs = pd.DataFrame({
    'feature': feature_names_transformed,
    'importance': feature_importances
})

# Ordenar las características por importancia
coefs_sorted = coefs.sort_values(by='importance')

# Guardar en un archivo CSV
#coefs_sorted.to_csv('FeatureImportances_mlp.csv', index=False)

# Creando el gráfico con Plotly
fig = px.bar(coefs_sorted, y='feature', x='importance', orientation='h',
             title='Importancia Aproximada de las Características - MLP',
             color_discrete_sequence=custom_colors)
fig.show()

Resultados#

# Nombres de los modelos
nombres_modelos = ['Ridge', 'Lasso', 'XGBoost', 'MLP']

# Definir las listas de métricas para cada modelo
mape_scores = [mape_ridge, mape_lasso, mape_xgboost, mape_mlp]
rmse_scores = [rmse_ridge, rmse_lasso, rmse_xgboost, rmse_mlp]
r2_scores = [r2_ridge, r2_lasso, r2_xgboost, r2_mlp]

# Crear un DataFrame para almacenar las métricas
df_resultados = pd.DataFrame({
    'Modelo': nombres_modelos,
    'MAPE': mape_scores,
    'RMSE': rmse_scores,
    'R^2': r2_scores
})

print(df_resultados)
    Modelo      MAPE          RMSE       R^2
0    Ridge  0.332810  1.963701e+08  0.761658
1    Lasso  0.332825  1.963725e+08  0.761652
2  XGBoost  0.192440  1.076223e+08  0.928410
3      MLP  0.303903  1.941895e+08  0.766922

Mejor modelo basado en la métrica RMSE#

# Encontrar el índice del modelo con el RMSE más bajo
indice_mejor_rmse = rmse_scores.index(min(rmse_scores))

# Obtiener el nombre del modelo con el RMSE más bajo
mejor_modelo = nombres_modelos[indice_mejor_rmse]

# Mostrar el modelo con el RMSE más bajo y su valor de RMSE
print(f"El modelo con el RMSE más bajo es {mejor_modelo} con RMSE = {min(rmse_scores)}")
El modelo con el RMSE más bajo es XGBoost con RMSE = 107622322.47698922

Mejor modelo basado en la métrica \(R^2\)#

# Encontrar el índice del modelo con el r2 más alto
indice_mejor_r2 = r2_scores.index(max(r2_scores))

# Obtiener el nombre del modelo con el r2 más alto
mejor_modelo2 = nombres_modelos[indice_mejor_r2]

# Mostrar el modelo con el r2 más alto y su valor de r2
print(f"El modelo con el r2 más alto es {mejor_modelo2} con r2 = {max(r2_scores)}")
El modelo con el r2 más alto es XGBoost con r2 = 0.9284097078636615

Gráfica de métricas#

# Gráfica de R2
fig_r2 = go.Figure()
fig_r2.add_trace(go.Bar(
    y=nombres_modelos,
    x=r2_scores,
    name='R^2',
    orientation='h',
    marker=dict(color=custom_colors[0])
))
fig_r2.update_layout(
    title='Comparación de R^2 entre Modelos',
    xaxis=dict(title='R^2'),
    yaxis=dict(title='Modelos'),
    barmode='group',
    bargap=0.15,
    bargroupgap=0.1
)
fig_r2.show()

# Gráfica de RMSE
fig_rmse = go.Figure()
fig_rmse.add_trace(go.Bar(
    y=nombres_modelos,
    x=rmse_scores,
    name='RMSE Score',
    orientation='h',
    marker=dict(color=custom_colors[1])
))
fig_rmse.update_layout(
    title='Comparación de RMSE entre Modelos',
    xaxis=dict(title='RMSE Score'),
    yaxis=dict(title='Modelos'),
    barmode='group',
    bargap=0.15,
    bargroupgap=0.1
)
fig_rmse.show()